package com.xxxx.spring.day10;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;

public class Proxy extends Target{

    // 方法的拦截器  类似于JDK代理中的InvocationHandler
    // 自定义实现它来插入增强逻辑
    private MethodInterceptor methodInterceptor;

    public void setMethodInterceptor(MethodInterceptor methodInterceptor){
        this.methodInterceptor = methodInterceptor;
    }

    /**
     * 静态方法初始化:
     *      通过反射获取Target类的方法 （save0 , save1 , save2）
     * 为每个方法创建对应的MethodProxy (如save1Proxy) ,指定：
     *     目标类（Target.class）
     *     代理类（Proxy.class）
     *     方法签名 (如 ()V 表示无参void方法 )
     *     代理方法名(save)
     *     调用父类原始方法的方法名(saveSuper)
     */
    static Method save0;
    static Method save1;
    static Method save2;
    static MethodProxy save1Proxy;
    static MethodProxy save2Proxy;
    static MethodProxy save3Proxy;
    static {
        try{
            save0 = Target.class.getMethod("save");
            save1 = Target.class.getMethod("save", int.class);
            save2 = Target.class.getMethod("save", long.class);
            /**
             * MethodProxy.create()参数说明：
             *              目标类
             *              代理类
             *              方法描述符（如"()V"表示无参void方法）
             *              方法名
             *              调用父类方法的方法名
             */
            save1Proxy = MethodProxy.create(Target.class,Proxy.class,"()V","save","saveSuper");
            save2Proxy = MethodProxy.create(Target.class,Proxy.class,"(I)V","save","saveSuper");
            save3Proxy = MethodProxy.create(Target.class,Proxy.class,"(J)V","save","saveSuper");
        } catch (NoSuchMethodException e){
            throw new NoSuchMethodError(e.getMessage());
        }
    }

    // >>>>>>>>  带原始功能的方法

    /**
     * 这些方法提供了直接调用父类（目标类）原始实现的途径
     * 在拦截器中可以用来调用原始方法
     */
    public void saveSuper(){
        super.save();
    }

    public void saveSuper(int i){
        super.save(i);
    }

    public void saveSuper(long j){
        super.save(j);
    }




    // >>>>>>>>  带增强功能的方法
    /**
     * 重写父类方法，加入拦截逻辑
     *  methodInterceptor.intercept(this, save0, new Object[0], save1Proxy) 这段代码并不会直接调用父类方法，
     *  而是将方法的调用权交给拦截器（MethodInterceptor），由拦截器决定如何处理这次调用（是否调用原始方法、是否增强逻辑等）
     *
     * 调用methodInterceptor.intercept()方法，参数包括：
     *              代理对象本身(this)
     *              被调用的方法(save0/save1/save2)
     *              方法参数
     *              方法代理对象(MethodProxy)
     */
    @Override
    public void save() {
        try {
            methodInterceptor.intercept(this, save0, new Object[0], save1Proxy);
        }catch (Throwable e){
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public void save(int i) {
        try {
            methodInterceptor.intercept(this, save1, new Object[]{i}, save2Proxy);
        }catch (Throwable e){
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public void save(long j) {
        try {
            methodInterceptor.intercept(this, save2, new Object[]{j}, save3Proxy);
        }catch (Throwable e){
            throw new UndeclaredThrowableException(e);
        }
    }
}
